package com.own.business.push.module.vivo.client;

import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.own.business.push.core.base.BasePushClientMethod;
import com.own.business.push.core.model.MessagePushContentModel;
import com.own.business.push.module.vivo.property.PushVivoProperty;
import com.own.component.common.exception.BusinessSimpleException;
import com.own.component.common.util.encrypt.EncryptUtil;
import com.own.component.store.core.Store;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.List;
import java.util.UUID;

/**
 * PushVivoClient
 *
 * @author chenxueli
 * @date 2023-11-16 10:59:28
 */
@Slf4j
@Component
public class PushVivoClient implements BasePushClientMethod {

    private static final String HOST = "https://api-push.vivo.com.cn";
    private static final String PUSH_TOKEN_KEY = "w:c:token:vivo";

    @Resource
    private PushVivoProperty pushVivoProperty;

    @Resource
    private Store<String> store;

    /**
     * 全量推送
     *
     * @param contentModel 内容
     */
    @Override
    public void all(MessagePushContentModel contentModel) {
        log.info("vivo全量推送暂不支持");
    }

    /**
     * 注册id推送
     *
     * @param regId        注册id列表
     * @param contentModel 内容
     */
    @Override
    public void regId(String regId, MessagePushContentModel contentModel) {
        var data = buildSingleContent(contentModel);
        data.put("regId", regId);
        var request = HttpRequest.post(HOST + "/message/send")
                .header("authToken", getAuthorization())
                .contentType("application/json")
                .body(JSON.toJSONString(data))
                .execute();
        var body = request.body();
        log.info("vivo推送结果:{}", body);
    }

    /**
     * 注册id推送
     *
     * @param regIdList    注册id列表
     * @param contentModel 内容
     */
    @Override
    public void regId(List<String> regIdList, MessagePushContentModel contentModel) {
        var taskId = saveListPayload(contentModel);
        // 构造新的请求内容
        var data = new JSONObject();
        data.put("appId", pushVivoProperty.getAppId());
        data.put("taskId", taskId);
        data.put("regIds", regIdList);
        data.put("requestId", UUID.randomUUID().toString());
        data.put("pushMode", pushVivoProperty.getDev() ? 0 : 1);
        var request = HttpRequest.post(HOST + "/message/pushToList")
                .header("authToken", getAuthorization())
                .form(JSON.toJSONString(data))
                .execute();
        var body = request.body();
        log.info("vivo推送结果:{}", body);
    }

    /**
     * 别名推送信息
     *
     * @param alias        别名
     * @param contentModel 内容
     */
    @Override
    public void alias(String alias, MessagePushContentModel contentModel) {
        var data = buildSingleContent(contentModel);
        data.put("alias", alias);
        var request = HttpRequest.post(HOST + "/message/send")
                .header("authToken", getAuthorization())
                .contentType("application/json")
                .body(JSON.toJSONString(data))
                .execute();
        var body = request.body();
        log.info("vivo推送结果:{}", body);
    }

    /**
     * 别名推送信息
     *
     * @param aliasList    别名列表
     * @param contentModel 内容
     */
    @Override
    public void alias(List<String> aliasList, MessagePushContentModel contentModel) {
        var taskId = saveListPayload(contentModel);
        // 构造新的请求内容
        var data = new JSONObject();
        data.put("appId", pushVivoProperty.getAppId());
        data.put("taskId", taskId);
        data.put("aliases", aliasList);
        data.put("requestId", UUID.randomUUID().toString());
        data.put("pushMode", pushVivoProperty.getDev() ? 0 : 1);
        var request = HttpRequest.post(HOST + "/message/pushToList")
                .header("authToken", getAuthorization())
                .form(JSON.toJSONString(data))
                .execute();
        var body = request.body();
        log.info("vivo推送结果:{}", body);
    }

    /**
     * 构造推送内容（单个消息）
     *
     * @param contentModel 内容
     * @return 推送内容
     */
    private JSONObject buildSingleContent(MessagePushContentModel contentModel) {
        var data = new JSONObject();
        data.put("appId", pushVivoProperty.getAppId());
        data.put("notifyType", 4);
        data.put("title", contentModel.getNotificationTitle());
        data.put("content", contentModel.getContent());
        data.put("skipType", 3);
        data.put("requestId", UUID.randomUUID().toString());
        data.put("clientCustomMap", contentModel.getExtras());
        data.put("pushMode", pushVivoProperty.getDev() ? 0 : 1);
        return data;
    }

    /**
     * 保存群推消息公共体接口
     *
     * @param contentModel 消息内容
     * @return 任务id
     */
    private String saveListPayload(MessagePushContentModel contentModel) {
        var data = buildSingleContent(contentModel);
        data.remove("pushMode");
        var request = HttpRequest.post(HOST + "/message/saveListPayload")
                .header("authToken", getAuthorization())
                .contentType("application/json")
                .body(JSON.toJSONString(data))
                .execute();
        var jsonObject = JSON.parseObject(request.body());
        var taskId = jsonObject.getString("taskId");
        if (StringUtils.isBlank(taskId)) {
            var desc = jsonObject.getString("desc");
            throw new BusinessSimpleException(StringUtils.isBlank(desc) ? "保存群推消息失败" : desc);
        }
        return taskId;
    }

    /**
     * 获取认证请求头
     * 接口返回的参数authToken，一个appId可对应多个token，24小时过期，业务方做中心缓存，1-2小时更新一次。
     *
     * @return 认证请求头
     */
    private String getAuthorization() {
        // 查询缓存中的token信息
        var token = store.value().get(PUSH_TOKEN_KEY);
        if (StringUtils.isNotBlank(token)) {
            return token;
        }
        var timestamp = System.currentTimeMillis();
        var sign = EncryptUtil.MD5.encrypt(pushVivoProperty.getAppId() + pushVivoProperty.getKey() + timestamp + pushVivoProperty.getSecret()).toLowerCase();
        var data = new JSONObject();
        data.put("appId", pushVivoProperty.getAppId());
        data.put("appKey", pushVivoProperty.getKey());
        data.put("timestamp", timestamp);
        data.put("sign", sign);
        // 执行请求
        var request = HttpRequest.post(HOST + "/message/auth")
                .contentType("application/json")
                .body(JSON.toJSONString(data))
                .execute();
        var jsonObject = JSON.parseObject(request.body());
        var authToken = jsonObject.getString("authToken");
        if (StringUtils.isBlank(authToken)) {
            var desc = jsonObject.getString("desc");
            throw new BusinessSimpleException(StringUtils.isBlank(desc) ? "获取vivo推送token失败" : desc);
        }
        store.value().set(PUSH_TOKEN_KEY, authToken, Duration.ofHours(24));
        return authToken;
    }

    /**
     * 推送发送的名称
     *
     * @return 名称
     */
    @Override
    public String name() {
        return "vivo";
    }

}
